﻿#ifndef TYPETRATE_H
#define TYPETRATE_H

#include <type_traits>

template<typename T>
struct GetDefaultConstruct
{
    static void* Fun(void* buff){
        return (void*)(new (buff)T());
    }
};

template<typename T>
struct GetCopyConstruct
{
    static void* Fun(void* buff,const void* other){
        return  new (buff)T(*(const T*)other);
    }
};

template <typename T>
struct GetEqualFunction
{
    static bool Fun(void* o1,void* o2){
        return *(T*)o1 == *(T*)o2;
    }
};


template <typename T>
struct GetAssignFunction
{
static void Fun(void* o1,const void* o2){
    *(T*)o1 = *(const T*)o2;
}
};

template <typename T>
struct GetDestructor{
    static void Fun(void* o){
        T* t = (T*)o;
        t->~T();
    }
};

inline const void* ParamExpand(int &i,const void** param){
    i--;
    return param[i];
}

template<typename ...Args>
class OverLoad
{
public:
	template<typename R>
    static auto of(R(*p)(Args...)) ->decltype (p){
		return p;
	}

	template<typename R, typename T>
    static auto of(R(T::*p)(Args...)) ->decltype (p){
		return p;
	}
};

template <typename Base,typename T>
class DerivedOrSame
{
public:
    static constexpr bool value = std::is_same<Base,T>::value || std::is_base_of<Base,T>::value;
};

template <typename T>
class NormalizeType
{
private:
	typedef typename std::remove_reference<T>::type _Type;
public:
	typedef typename std::remove_const<typename _Type>::type Type;
};


template<class T> using InvokeGenSeq = typename T::Type;

template<int...> struct IndexesList { using Type = IndexesList; };

template<int N, class S1, class S2> struct ConcatSeqImpl;

template<int N, int... I1, int... I2>
struct ConcatSeqImpl<N, IndexesList<I1...>, IndexesList<I2...>>
	: IndexesList<I1..., (N + I2)...> {};

template<int N, class S1, class S2>
using ConcatSeq = InvokeGenSeq<ConcatSeqImpl<N, S1, S2>>;

template<int N> struct GenSeq;
template<int N> using makeIndexSequence = InvokeGenSeq<GenSeq<N>>;

template<int N>
struct GenSeq : ConcatSeq<N / 2, makeIndexSequence<N / 2>, makeIndexSequence<N - N / 2>> {};

template<> struct GenSeq<0> : IndexesList<> {};
template<> struct GenSeq<1> : IndexesList<0> {};

template<int N>
struct Indexes { using Value = makeIndexSequence<N>; };

template<typename ...Args>
struct ArgList
{

};

#endif // TYPETRATE_H
